﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

using Styx.WoWInternals.DBC;
using Styx.WoWInternals.WoWObjects;
using Styx.WoWInternals;
using Styx.Common;
using Styx.CommonBot.Routines;
using Styx.Helpers;
using Styx.Pathing;
using Styx;
using System.Diagnostics;
using System.Threading;
using System.IO;
using Styx.CommonBot;
using System.Windows.Forms;
using Styx.CommonBot.Inventory;

namespace KingWoW
{
    public class ShadowPriestCombatClass : KingWoWAbstractBaseClass
    {
        
        private static string Name = "KingWoW 2 ShadowPriest";

        #region CONSTANT AND VARIABLES
        //START OF CONSTANTS AND VARIABLES ==============================
        private static bool IsCRPaused = false;
        private static KingWoWUtility utils = null;
        private Movement movement = null;
        private ExtraUtils extra = null;

        private WoWUnit tank = null;
        private WoWUnit off_tank = null;
        private WoWUnit lastTank = null;
        private WoWUnit lastOffTank = null;
        int enemyAroundMainTank = 0;
        int enemyAroundOffTank = 0;
        int MaxOrbs = 3;

        private float RangeOfAttack = 40f;

            
        private bool SoloBotType = false;
        private string BaseBot = "unknown";
        private TalentManager talents = null;
        WoWUnit target = null;

        private const string TANK_CHANGE = "TANK CHANGED";
        private const string OFF_TANK_CHANGE = "OFFTANK CHANGED";
        private const string FACING = "FACING";

        //START OF SPELLS AND AURAS ==============================
        private const int DISPELL_MAGIC = 528;
        private const int SHACKLE_UNDEAD = 9484;
        private const int MIND_SEAR = 48045;
        private const int LEAP_OF_FAITH = 73325;
        private const int PRAYER_OF_HEALING = 596;
        private const int PRAYER_OF_MENDING = 33076;
        private const int POWER_WORD_SHIELD = 17;
        private const int POWER_WORD_FORTITUDE = 21562;
        private const int POWER_WORD_SOLACE = 129250;
        private const int SHADOW_WORD_PAIN = 589;
        private const string SHADOW_WORD_PAIN_STRING = "Shadow Word: Pain";
        private const int SHADOW_WORD_DEATH = 32379;
        private const int MIND_BLAST_PROC = 124430;//109175;
        private const int FEAR_WARD = 6346;
        private const int MASS_DISPEL = 32375;
        private const int POWER_INFUSION = 10060;
        private const int FLASH_HEAL = 2061;
        private const int GREATER_HEAL = 2060;
        private const int HEAL = 2050;
        private const int SURGE_OF_LIGHT = 114255; // 1 stack --> 128654   talent spell 109186
        private const int HOLY_FIRE = 14914;
        private const int DESPERATE_PRAYER = 19236;
        private const int RESURRECTION = 2006;
        private const int SMITE = 585;
        private const int FADE = 586;
        private const int SHADOWFIEND = 34433;
        private const int MINDBENDER = 123040;
        private const int WEAKENED_SOUL = 6788;
        private const int LEVITATE = 1706;
        private const string CASCADE = "Cascade";
        private const string HALO = "Halo";
        private const string DIVINE_STAR = "Divine Star";
        private const int ANGELIC_FEATHER = 121536;
        private const int ANGELIC_FEATHER_AURA = 121557;
        private const int PSYCHIC_SCREAM = 8122;
        private const int VOID_TENDRILS = 108920;
        private const int PSYFIEND = 108921;

        
        private const int DARK_INTENT = 109773;

        //private const double time_dispell = 3000;

        //private const string DRINK = "Drink";
        //private const string FOOD = "Food";

        private const int SILENCE = 15487;
        private const int DEVOURING_PLAGUE = 2944;
        private const string DEVOURING_PLAGUE_STRING = "Devouring Plague";
        private const int MIND_BLAST = 8092;
        private const int VAMPIRIC_TOUCH = 34914;
        private const string VAMPIRIC_TOUCH_STRING = "Vampiric Touch";
        private const int DISPERSION = 47585;
        private const int VAMPIRIC_EMBRANCE = 15286;
        private const int MIND_SPIKE = 73510;
        private const int SURGE_OF_DARKNESS = 87160;
        private const int MIND_FLY = 15407;
        private const int MIND_FLY_INSANITY = 129197;
        private const int SEARING_INSANITY = 179338;
        private const int SHADOW_WORD_INSANITY = 132573;
        private const string VOID_ENTROPY = "Void Entropy";

        private const string SHADOWFORM = "Shadowform";
        //END OF SPELLS AND AURAS ==============================
        private Random rnd = new Random();
        private int RANDOM_TIME = 0;
        //END OF CONSTANTS ==============================
        #endregion

        #region Hotkeys
        private static Hotkey pauseHotkey, massDispelHotkey;
        
        private static void InitializeHotkey()
        {
            if (StyxWoW.Me.Specialization == WoWSpec.PriestShadow)
            {
                HotkeysManager.Initialize(StyxWoW.Memory.Process.MainWindowHandle);
            }
        }

        private static Hotkey RegisterHotkeyAssignment(string name, Keys key, Action<Hotkey> callback)
        {
            Keys keyCode = key & Keys.KeyCode;
            ModifierKeys mods = ModifierKeys.NoRepeat;

            if ((key & Keys.Shift) != 0)
                mods |= ModifierKeys.Shift;
            if ((key & Keys.Alt) != 0)
                mods |= ModifierKeys.Alt;
            if ((key & Keys.Control) != 0)
                mods |= ModifierKeys.Control;

            return HotkeysManager.Register(name, keyCode, mods, callback);
        }

        private static void RegisterHotkeys()
        {
            if (StyxWoW.Me.Specialization == WoWSpec.PriestShadow)
            {
                pauseHotkey = RegisterHotkeyAssignment("SHADOW Routine Pause", (Keys)ShadowPriestSettings.Instance.PauseKey, hk =>
                {
                    try
                    {
                        if (!IsCRPaused)
                        {
                            IsCRPaused = true;
                            if (ExtraUtilsSettings.Instance.ViewChatMessages)
                                Lua.DoString(@"print('\124cFFE61515 Paused!')");
                            Logging.Write("KingWoW Routine Paused!");
                        }
                        else
                        {
                            IsCRPaused = false;
                            if (ExtraUtilsSettings.Instance.ViewChatMessages)
                                Lua.DoString(@"print('\124cFF15E61C Resumed!')");
                            Logging.Write("KingWoW Routine Resumed!");
                        }
                    }
                    catch (Exception e)
                    {
                        Logging.Write(e.StackTrace);
                    }
                });
                massDispelHotkey = RegisterHotkeyAssignment("SHADOW MassDispellOnHotkey", (Keys)ShadowPriestSettings.Instance.MassDispellOnHotkey, hk =>
                {
                    try
                    {
                        Logging.Write("MassDispell HOTKEY PRESSED!");
                        TryPutMassDispell = true;
                        HotkeyTimer.AutoReset = false;
                        HotkeyTimer.Interval = 2000;
                        HotkeyTimer.Start();
                    }
                    catch (Exception e)
                    {
                        Logging.Write(e.StackTrace);
                    }
                });
            }
        }

        private static bool TryPutMassDispell = false;
        private static System.Timers.Timer HotkeyTimer = new System.Timers.Timer();

        private bool HotkeyHandle()
        {
            if (TryPutMassDispell && utils.CanCast(MASS_DISPEL))
            {
                utils.LogActivity("MassDispell On Mouse position");
                utils.Cast(MASS_DISPEL);
                utils.PerformSingleLeftMouseClick();
                return true;
            }
            return false;
        }

        void HotkeyTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            TryPutMassDispell = false;
        }

        private static void RemoveHotkeys()
        {
            if (StyxWoW.Me.Specialization == WoWSpec.PriestShadow)
            {
                //Holy HOTKEY
                HotkeysManager.Unregister("HOLY Routine Pause");
                HotkeysManager.Unregister("HOLY HWSanctuaryOnHotkey");
                HotkeysManager.Unregister("HOLY Blanket_RENEW_Hotkey");
                HotkeysManager.Unregister("HOLY Change_CHAKRA_Hotkey");
                HotkeysManager.Unregister("HOLY MassDispellOnHotkey");
                HotkeysManager.Unregister("HOLY Change_NPC_Healing_Hotkey");
                //Disci HOTKEY
                HotkeysManager.Unregister("DISCI Routine Pause");
                HotkeysManager.Unregister("DISCI UseDisciplineAtonementHealingRotation");
                HotkeysManager.Unregister("DISCI BarrierOnHotkey");
                HotkeysManager.Unregister("DISCI Blanket_PWS_Hotkey");
                HotkeysManager.Unregister("DISCI MassDispellOnHotkey");
                HotkeysManager.Unregister("DISCI Change_NPC_Healing_Hotkey");
                //shadow HOTKEY
                HotkeysManager.Unregister("SHADOW Routine Pause");
                HotkeysManager.Unregister("SHADOW MassDispellOnHotkey");
            }
        }

        private static void ReRegisterHotkeys()
        {
            if (StyxWoW.Me.Specialization == WoWSpec.PriestShadow)
            {
                Logging.Write("SHADOW: ReRegisterHotkeys");
                RemoveHotkeys();
                RegisterHotkeys();
            }
        }
        #endregion

        public ShadowPriestCombatClass()
        {
            utils = new KingWoWUtility();
            movement = new Movement();
            extra = new ExtraUtils();
            tank = null;
            lastTank = null;
            off_tank = null;
            lastOffTank = null;
            SoloBotType = false;
            BaseBot = "unknown";
            talents = new TalentManager();
            nextTimeTryReviveAllowed = DateTime.Now;
            HotkeyTimer.Elapsed += HotkeyTimer_Elapsed;
        }

        public override bool Pulse
        {
            get
            {
                if (Me.IsDead) return MyDeath();
                                
                if (Me.Combat || (Me.Mounted && !ShadowPriestSettings.Instance.AutoDismountOnCombat) || !StyxWoW.IsInGame || !StyxWoW.IsInWorld || Me.Silenced || utils.IsGlobalCooldown(true) || utils.MeIsChanneling || Me.IsCasting
                || utils.IsEatingOrDrinking() || IsCRPaused)
                    return false;

                tank = utils.SimpleGetTank(40f);
                if (tank == null || !tank.IsValid || !tank.IsAlive) tank = Me;

                if (tank != null && (lastTank == null || lastTank.Guid != tank.Guid))
                {
                    lastTank = tank;
                    utils.LogActivity(TANK_CHANGE, tank.SafeName);
                }
                off_tank = utils.SimpleGetOffTank(40f, tank);
                if (off_tank != null && (lastOffTank == null || lastOffTank.Guid != off_tank.Guid))
                {
                    lastOffTank = off_tank;
                    utils.LogActivity(OFF_TANK_CHANGE, off_tank.SafeName);
                }
                if (ShadowPriestSettings.Instance.BurstSpeedMoving && Me.IsMoving && !Me.Mounted && !Me.IsFalling && !Me.IsDead && !Me.IsGhost
                    && Me.MovementInfo.TimeMoved >= ShadowPriestSettings.Instance.MoveTimeForSpeedBuff && !IsCRPaused)
                {
                    if (talents.IsSelected(5) && !utils.isAuraActive(ANGELIC_FEATHER_AURA) && utils.CanCast(ANGELIC_FEATHER))
                    {
                        utils.LogActivity("moving....ANGELIC_FEATHER");
                        utils.Cast(ANGELIC_FEATHER);
                        SpellManager.ClickRemoteLocation(Me.Location);
                        Lua.DoString("SpellStopTargeting()");
                        return true;
                    }
                    if (talents.IsSelected(4) && !utils.isAuraActive(WEAKENED_SOUL, Me) && !utils.isAuraActive(POWER_WORD_SHIELD, Me) && utils.CanCast(POWER_WORD_SHIELD))
                    {
                        utils.LogActivity("moving....POWER_WORD_SHIELD");
                        return utils.Cast(POWER_WORD_SHIELD, Me);
                    }

                }
                HotkeyHandle();
                 //full party or me
                if (!Me.Mounted && !IsCRPaused && ShadowPriestSettings.Instance.OOCHealing && Me.HealthPercent <= ShadowPriestSettings.Instance.OOCHealingHP)
                {
                    if (!Me.IsMoving && utils.CanCast(FLASH_HEAL) && Me.ManaPercent >= 30)
                    {
                        utils.LogActivity("OOC Healing: " + FLASH_HEAL);
                        return utils.Cast(FLASH_HEAL, Me);
                    }
                }
                
                if (!Me.Combat && ((tank != null && tank.Combat) || (off_tank != null && off_tank.Combat)))
                {
                    if (talents.IsSelected(19) && ShadowPriestSettings.Instance.EnableDotWeavingRotation)
                        return DotWeavingRotation();
                    return CombatRotation();
                }
                return false;
            }
        }

        public override bool Initialize
        {
            get
            {
                Logging.Write("Ciao " + Me.Class.ToString());
                Logging.Write("Welcome to " + Name + " custom class");
                Logging.Write("Tanks All HonorBuddy Forum developers for code inspiration!");
                Logging.Write("Powered by Attilio76");

                BotEvents.OnBotStartRequested += new BotEvents.OnBotStartStopRequestedDelegate(BotEvents_OnBotStart);
                Logging.Write("Initializing Hotkey");
                InitializeHotkey();
                ReRegisterHotkeys();
                Logging.Write("************ XML CONFIGURATION ************");
                Logging.Write(ShadowPriestSettings.Instance.GetXML().ToString());
                Logging.Write("*******************************************");
                Logging.Write("*******************************************");
                Logging.Write("*******************************************");
                Logging.Write("************ EXTRA CONFIGURATION ************");
                Logging.Write(ExtraUtilsSettings.Instance.GetXML().ToString());
                Logging.Write("*******************************************");
                return true; ;
            }
        }

        void BotEvents_OnBotStart(EventArgs args)
        {
            talents.Update();
            BotUpdate();
            MaxOrbs = GetMaxOrb();
            ReRegisterHotkeys();
            Logging.Write("Max Orbs set to " + MaxOrbs);
        }

        public override bool UpdateTalentAndGlyph
        {
            get
            {
                talents.Update();
                BotUpdate();
                MaxOrbs = GetMaxOrb();
                ReRegisterHotkeys();
                Logging.Write("Max Orbs set to " + MaxOrbs);
                return true;
            }
        }

        public override bool NeedRest
        {
            get
            {
                if (Me.IsDead || Me.Mounted || Me.InVehicle || (Me.HealthPercent >= 100 && Me.ManaPercent >= 100)) return false;
                if (utils.IsEatingOrDrinking())
                    return true;
                if (Me.ManaPercent <= ShadowPriestSettings.Instance.ManaPercent
                    && !Me.Combat && !Me.IsMoving && !utils.IsEatingOrDrinking())
                {
                    WoWItem mydrink = Consumable.GetBestDrink(false);
                    if (mydrink != null)
                    {
                        utils.LogActivity("Drinking");
                        Styx.CommonBot.Rest.DrinkImmediate();
                        return true;
                    }
                    return true;
                }
                if (Me.HealthPercent <= ShadowPriestSettings.Instance.HealthPercent
                    && !Me.Combat && !Me.IsMoving && !utils.IsEatingOrDrinking())
                {
                    WoWItem myfood = Consumable.GetBestFood(false);
                    if (myfood != null)
                    {
                        utils.LogActivity("Eating");
                        Styx.CommonBot.Rest.DrinkImmediate();
                        return true;
                    }
                    return true;
                }
                return false;
            }
        }

        public override bool NeedPullBuffs { 
            get 
            {
                return ShadowPullBuff(); 
            } 
        }

        public override bool NeedCombatBuffs { get { return Cast(); } }

        public override bool NeedPreCombatBuffs { get { return Cast(); } }

        private DateTime nextTimeTryReviveAllowed;
        
        public void SetNextTimeTryRevive()
        {
            //2 seconds avoid duuble cast
            nextTimeTryReviveAllowed = DateTime.Now + new TimeSpan(0, 0, 0, 0, 3000);
        }

        private bool MyDeath()
        {
            if (SoloBotType && Me.IsDead && !Me.IsGhost && nextTimeTryReviveAllowed < DateTime.Now)
            {
                Lua.DoString(string.Format("RunMacroText(\"{0}\")", "/script RepopMe()"));
                SetNextTimeTryRevive();
            }
            return false;
        }

        private int GetMaxOrb()
        {
            if (SpellManager.HasSpell(157217))
                return 5;
            return 3;
        }

        public override bool Pull
        {
            get 
            {
                target = Me.CurrentTarget;
                if (target != null && target.IsDead)
                {
                    Me.ClearTarget();
                    SetTargetToAttack();
                    if(target!=null)
                        target.Target();
                }
                if ((SoloBotType || ShadowPriestSettings.Instance.movementEnabled) && Me.CurrentTarget != null && Me.IsMoving && Me.CurrentTarget.InLineOfSpellSight && Me.CurrentTarget.Distance - Me.CurrentTarget.CombatReach - 1 <= ShadowPriestSettings.Instance.PullDistance)
                {
                    Navigator.PlayerMover.MoveStop();
                }
                if (target != null && /*!target.IsFriendly &&*/ target.Attackable && !target.IsDead && !IsCRPaused)
                {
                    if (!target.InLineOfSpellSight || target.Distance - target.CombatReach -1  > ShadowPriestSettings.Instance.PullDistance)
                    {
                        movement.KingHealMove(target, ShadowPriestSettings.Instance.PullDistance);
                    }                   
                    if (!Me .IsMoving && !Me.IsFacing(target))
                    {
                        utils.LogActivity(FACING, target.SafeName);
                        Me.SetFacing(target);
                    }

                    if (talents.IsSelected(19) && ShadowPriestSettings.Instance.EnableDotWeavingRotation)
                    {
                        DotWeavingProcWork();
                        if (utils.CanCast(MIND_BLAST))
                        {
                            utils.LogActivity("MIND_BLAST", target.SafeName);
                            return utils.Cast(MIND_BLAST, target);
                        }
                        else if (!ShadowPriestSettings.Instance.fastPull)
                        {
                            utils.LogActivity("MIND_SPIKE", target.SafeName);
                            return utils.Cast(MIND_SPIKE, target);
                        }
                    }
                    ProcWork();
                    if (ShadowPriestSettings.Instance.fastPull)
                    {
                        //apply dot to my main target
                        if (utils.CanCast(SHADOW_WORD_PAIN) && utils.MyAuraTimeLeft(SHADOW_WORD_PAIN, target) < 5400)
                        {
                            utils.LogActivity("SHADOW_WORD_PAIN", target.SafeName);
                            return utils.Cast(SHADOW_WORD_PAIN, target);
                        }
                    }
                    if (!Me.IsMoving && !Me.IsCasting && !utils.IsGlobalCooldown() && Me.GetCurrentPower(WoWPowerType.ShadowOrbs) < MaxOrbs && utils.CanCast(VAMPIRIC_TOUCH))
                    {
                        /*if (utils.PreventDoubleCast(VAMPIRIC_TOUCH_STRING, 2.2, target))
                        {
                            utils.LogActivity("VAMPIRIC_TOUCH", target.SafeName);
                            return true;
                        }*/
                        utils.LogActivity("VAMPIRIC_TOUCH", target.SafeName);
                        return utils.Cast(VAMPIRIC_TOUCH, target);
                    }
                }
                return false;          
            }
        }

        private bool ShadowPullBuff()
        {
            if (utils.Mounted() || IsCRPaused)
                return false;
            if (!ShadowPriestSettings.Instance.fastPull && !utils.isAuraActive(POWER_WORD_FORTITUDE) && utils.CanCast(POWER_WORD_FORTITUDE))
            {
                utils.LogActivity("POWER_WORD_FORTITUDE");
                utils.Cast(POWER_WORD_FORTITUDE);
            }
            if (!Me.HasAura(SHADOWFORM) && utils.CanCast(SHADOWFORM)
                && (Me.Combat || !(ShadowPriestSettings.Instance.OOCHealing && Me.HealthPercent <= ShadowPriestSettings.Instance.OOCHealingHP && Me.ManaPercent >= 30)))
            {
                utils.LogActivity("SHADOWFORM", Me.Class.ToString());
                return utils.Cast(SHADOWFORM, Me);
            }

            foreach (WoWPlayer player in Me.PartyMembers)
            {
                if (player.Distance - player.CombatReach -1  > 40f || player.IsDead || player.IsGhost || !player.InLineOfSpellSight) continue;
                else if (!utils.isAuraActive(POWER_WORD_FORTITUDE, player) && utils.CanCast(POWER_WORD_FORTITUDE))
                {
                    utils.LogActivity("POWER_WORD_FORTITUDE", player.Class.ToString());
                    utils.Cast(POWER_WORD_FORTITUDE, player);
                }
            }

            if (ShadowPriestSettings.Instance.UseFearWard && utils.CanCast(FEAR_WARD) && !utils.isAuraActive(FEAR_WARD, Me))
            {
                utils.LogActivity("FEAR_WARD", Me.Class.ToString());
                return utils.Cast(FEAR_WARD, Me);
            }
            if (!ShadowPriestSettings.Instance.fastPull && !utils.isAuraActive(POWER_WORD_SHIELD, Me) && !utils.isAuraActive(WEAKENED_SOUL, Me) )
            {
                utils.LogActivity("PULL BUFF: POWER_WORD_SHIELD", Me.Class.ToString());
                utils.Cast(POWER_WORD_SHIELD, Me); //no return see below
            }
            return false; //return false or loop trying cast PULLBUFF (not implemented)
        }

        private bool BotUpdate()
        {
            if (BaseBot.Equals(BotManager.Current.Name))
                return false;
            if (utils.IsBotBaseInUse("LazyRaider") || utils.IsBotBaseInUse("Tyrael")
                || utils.IsBotBaseInUse("Raid Bot") || utils.IsBotBaseInUse("Enyo"))
            {
                SoloBotType = false;
                BaseBot = BotManager.Current.Name;
                Logging.Write("Base bot detected: " + BotManager.Current.Name);
                return true;
            }

            Logging.Write("Base bot detected: " + BotManager.Current.Name);
            SoloBotType = true;
            BaseBot = BotManager.Current.Name;
            return true;


        }
       
        private bool Self()
        {
            if ((Me.HealthPercent <= ShadowPriestSettings.Instance.DispersionHP)
                && utils.CanCast(DISPERSION))
            {
                utils.LogActivity("DISPERSION");
                return utils.Cast(DISPERSION);
            }
            if (Me.Combat && Me.HealthPercent <= ShadowPriestSettings.Instance.PWShieldPercent && !utils.isAuraActive(POWER_WORD_SHIELD, Me) && !utils.isAuraActive(WEAKENED_SOUL, Me) && utils.CanCast(POWER_WORD_SHIELD))
            {
                utils.LogHealActivity(Me, "POWER_WORD_SHIELD", Me.Class.ToString());
                return utils.Cast(POWER_WORD_SHIELD, Me);
            }
            if (Me.Combat && Me.HealthPercent <= ShadowPriestSettings.Instance.DesperatePrayerPercent && utils.CanCast(DESPERATE_PRAYER))
            {
                utils.LogHealActivity(Me,"DESPERATE_PRAYER");
                return utils.Cast(DESPERATE_PRAYER);
            }         
            if (!Me.IsMoving && utils.CanCast(FLASH_HEAL) && Me.HealthPercent <= ShadowPriestSettings.Instance.FlashHealPercent && Me.ManaPercent >= 40)
            {
                utils.LogActivity("SOS ME: " + FLASH_HEAL);
                return utils.Cast(FLASH_HEAL, Me);
            }
  
            return false;
        }

        private bool Interrupt()
        {
            if (ShadowPriestSettings.Instance.AutoInterrupt)
            {
                WoWUnit InterruptTargetCandidate = Me.FocusedUnit;
                if (InterruptTargetCandidate == null /*|| InterruptTargetCandidate.IsFriendly*/ || InterruptTargetCandidate.IsDead
                    || !InterruptTargetCandidate.Attackable || !InterruptTargetCandidate.InLineOfSpellSight
                    || InterruptTargetCandidate.Distance - InterruptTargetCandidate.CombatReach - 1 > 30f)
                {
                    if (Me.CurrentTarget != null && Me.CurrentTarget.Distance - Me.CurrentTarget.CombatReach - 1 <= 30f && Me.CurrentTarget.InLineOfSpellSight)
                        InterruptTargetCandidate = Me.CurrentTarget;
                    else if (target!=null && target.Distance - target.CombatReach - 1 <= 30f && target.InLineOfSpellSight )
                        InterruptTargetCandidate = target;
                }
                if (InterruptTargetCandidate != null && (InterruptTargetCandidate.IsCasting || InterruptTargetCandidate.IsChanneling)
                    && InterruptTargetCandidate.CanInterruptCurrentSpellCast && utils.CanCast(SILENCE, InterruptTargetCandidate)
                    && Me.IsFacing(InterruptTargetCandidate) 
                    && InterruptTargetCandidate.Distance - InterruptTargetCandidate.CombatReach - 1 <= 30f
                    && InterruptTargetCandidate.InLineOfSpellSight)
                {
                    RANDOM_TIME = rnd.Next(ShadowPriestSettings.Instance.Interrupt_MIN_Time, ShadowPriestSettings.Instance.Interrupt_MAX_Time);

                    if (InterruptTargetCandidate.CurrentCastStartTime.AddMilliseconds(RANDOM_TIME) <= DateTime.Now)
                    {
                        utils.LogActivity("SILENCE", InterruptTargetCandidate.SafeName);
                        return utils.Cast(SILENCE, InterruptTargetCandidate);
                    }
                }
            }
            return false;
        }

        private bool Cleansing()
        {
            if (ShadowPriestSettings.Instance.UseMassDispell)
            {
                WoWUnit player = utils.GetDispelTargetPriest(40f, false, ExtraUtilsSettings.Instance.UseBossLogic);

                if (player != null )
                {
                    if (ShadowPriestSettings.Instance.UseMassDispell && player.Distance - player.CombatReach -1  <= 30f && utils.MassDispelCountForPlayer(player, 15f) >= ShadowPriestSettings.Instance.MassDispellCount && utils.CanCast(MASS_DISPEL)) 
                    {
                        utils.LogActivity("MASS_DISPEL", player.Class.ToString());
                        //Blacklist.Add(player, new TimeSpan(0, 0, 2));
                        utils.Cast(MASS_DISPEL);
                        return SpellManager.ClickRemoteLocation(player.Location);
                    }
                }
            }
            return false;
        }

        private bool Resurrect()
        {
            foreach (WoWPlayer player in utils.GetResurrectTargets(40f))
            {
                if (Blacklist.Contains(player.Guid,BlacklistFlags.All)) continue;
                else
                {
                    if (player.Distance - player.CombatReach -1  > 40f || !player.InLineOfSpellSight) return false;
                    else if (utils.CanCast(RESURRECTION, player) && ShadowPriestSettings.Instance.UseResurrection && !Me.IsMoving)
                    {
                        utils.LogActivity("RESURRECTION", player.Class.ToString());
                        Blacklist.Add(player,BlacklistFlags.All, new TimeSpan(0, 0, 60));
                        return utils.Cast(RESURRECTION, player);
                    }

                    return false;
                }
            }

            return false;
        }

        private bool Cast()
        {
            if (utils.Mounted() || IsCRPaused || /*ExtraUtilsSettings.Instance.PauseRotation || */ !StyxWoW.IsInGame || !StyxWoW.IsInWorld
                || utils.IsEatingOrDrinking() || IsCRPaused)
                return false;

            if (Me.Combat && Me.HealthPercent <= ShadowPriestSettings.Instance.PWShieldPercent && !utils.isAuraActive(POWER_WORD_SHIELD, Me) && !utils.isAuraActive(WEAKENED_SOUL, Me) && utils.CanCast(POWER_WORD_SHIELD))
            {
                utils.LogHealActivity(Me, " Buff Me: POWER_WORD_SHIELD", Me.Class.ToString());
                return utils.Cast(POWER_WORD_SHIELD, Me);
            }

            if (ShadowPriestSettings.Instance.AutoPWFortitude)
            {
                if ((!utils.isAuraActive(POWER_WORD_FORTITUDE) && !utils.isAuraActive(DARK_INTENT)) && utils.CanCast(POWER_WORD_FORTITUDE))
                {
                    utils.LogActivity("POWER_WORD_FORTITUDE");
                    return utils.Cast(POWER_WORD_FORTITUDE);
                }

                foreach (WoWPlayer player in Me.PartyMembers)
                {
                    if (player.Distance - player.CombatReach -1  > 40f || player.IsDead || player.IsGhost || !player.InLineOfSpellSight) continue;
                    else if ((!utils.isAuraActive(POWER_WORD_FORTITUDE, player) && !utils.isAuraActive(DARK_INTENT, player)) && utils.CanCast(POWER_WORD_FORTITUDE))
                    {
                        utils.LogActivity("POWER_WORD_FORTITUDE", player.Class.ToString());
                        return utils.Cast(POWER_WORD_FORTITUDE, player);
                    }
                }
                if (CombatBuff())
                    return true;
            }
            return false;
        }

        private bool CombatBuff()
        {
            if (IsCRPaused)
                return false;
            if (!Me.HasAura(SHADOWFORM) && utils.CanCast(SHADOWFORM)
                && (Me.Combat || !(ShadowPriestSettings.Instance.OOCHealing && Me.HealthPercent <= ShadowPriestSettings.Instance.OOCHealingHP && Me.ManaPercent >= 30))
                && !Me.IsCasting && !Me.IsChanneling && !utils.IsGlobalCooldown())
            {
                utils.LogActivity("SHADOWFORM", Me.Class.ToString());
                return utils.Cast(SHADOWFORM, Me);
            }
            if (ShadowPriestSettings.Instance.UseFearWard && utils.CanCast(FEAR_WARD) && !utils.isAuraActive(FEAR_WARD, Me))
            {
                utils.LogActivity("FEAR_WARD", Me.Class.ToString());
                return utils.Cast(FEAR_WARD, Me);
            }
            
            if (ShadowPriestSettings.Instance.UseFade && Me.Combat && (Me.GroupInfo.IsInParty || Me.GroupInfo.IsInRaid) && (Targeting.GetAggroOnMeWithin(Me.Location, 30) > 0) && utils.CanCast(FADE))
            {
                utils.LogActivity("FADE");
                return utils.Cast(FADE);
            }

            if (ShadowPriestSettings.Instance.BurstSpeedMoving && Me.IsMoving && !Me.IsCasting && !Me.IsChanneling && !Me.Mounted && !Me.IsFalling
                && (Me.Combat || Me.MovementInfo.TimeMoved >= ShadowPriestSettings.Instance.MoveTimeForSpeedBuff))
            {
                if (talents.IsSelected(5) && !utils.isAuraActive(ANGELIC_FEATHER_AURA) 
                    && utils.GetSpellCooldown(ANGELIC_FEATHER).Milliseconds <= 2*StyxWoW.WoWClient.Latency)
                {
                    utils.LogActivity("moving....ANGELIC_FEATHER");
                    utils.Cast(ANGELIC_FEATHER);
                    SpellManager.ClickRemoteLocation(Me.Location);
                    Lua.DoString("SpellStopTargeting()");
                    return true;
                }
                if (talents.IsSelected(4) && !utils.isAuraActive(WEAKENED_SOUL, Me) && !utils.isAuraActive(POWER_WORD_SHIELD, Me) && utils.CanCast(POWER_WORD_SHIELD))
                {
                    utils.LogActivity("moving....POWER_WORD_SHIELD");
                    return utils.Cast(POWER_WORD_SHIELD,Me);
                }

            }

            return false;
        }

        private void SetTargetToAttack()
        {
            if (ShadowPriestSettings.Instance.TargetTypeSelected == ShadowPriestSettings.TargetType.AUTO)
            {
                if (ExtraUtilsSettings.Instance.provinGround_Targeting)
                    target = utils.getAnyTargetToAttack(40f);
                else
                    target = utils.getTargetToAttack(40, tank, false, ExtraUtilsSettings.Instance.UseBossLogic);
                if (target != null)
                    target.Target();
            }
            else
                target = Me.CurrentTarget;
        }

        private bool ProcWork()
        {
            if (target != null)
            {
                if ((ShadowPriestSettings.Instance.AutofaceTarget || SoloBotType) && !Me.IsFacing(target) && !Me.IsMoving)
                {
                    Me.SetFacing(target);
                }
                if (Me.GetCurrentPower(WoWPowerType.ShadowOrbs) < MaxOrbs && target.HealthPercent <= 20
                    && utils.GetSpellCooldown(SHADOW_WORD_DEATH).Milliseconds <= 2 * StyxWoW.WoWClient.Latency)
                {
                    utils.LogActivity("procworks: SHADOW_WORD_DEATH", target.SafeName);
                    return utils.Cast(SHADOW_WORD_DEATH, target);
                }
                if (AutoDeathTargetAttack()) return true;

                if ((!Me.IsMoving || utils.isAuraActive(MIND_BLAST_PROC)) && Me.IsFacing(target) && Me.GetCurrentPower(WoWPowerType.ShadowOrbs) < MaxOrbs
                    && utils.GetSpellCooldown(MIND_BLAST).TotalMilliseconds <= 2 * StyxWoW.WoWClient.Latency)
                {
                    utils.LogActivity("procworks: MIND_BLAST", target.SafeName);
                    return utils.Cast(MIND_BLAST, target);
                }

                //devouring plague
                if (Me.GetCurrentPower(WoWPowerType.ShadowOrbs) >= 3)
                {
                    if (talents.IsSelected(20))
                    {
                        if (!utils.isMyAuraActive(VOID_ENTROPY, target) && utils.TimeToDeath(target) > 10)
                        {
                            utils.LogActivity("procworks: VOID_ENTROPY", target.SafeName);
                            return utils.Cast(VOID_ENTROPY, target);
                        }
                        else
                        {
                            WoWUnit TargetForEntropy = utils.NextApplyAuraTarget(VOID_ENTROPY, 40f, 1000, ShadowPriestSettings.Instance.MultidotAvoidCC);
                            if (TargetForEntropy != null && TargetForEntropy.Distance - TargetForEntropy.CombatReach - 1 <= 40f)
                            {
                                utils.LogActivity("   MULTIDOT VOID_ENTROPY  ", TargetForEntropy.SafeName);
                                return utils.Cast(VOID_ENTROPY, TargetForEntropy);
                            }
                        }
                    }
                    if (!utils.isMyAuraActive(DEVOURING_PLAGUE_STRING, target) && utils.TimeToDeath(target) > 10)
                    {
                        utils.LogActivity("procworks: DEVOURING_PLAGUE", target.SafeName);
                        return utils.Cast(DEVOURING_PLAGUE, target);
                    }
                    else
                    {
                        WoWUnit TargetForDevouringPlague = utils.NextApplyAuraTarget(DEVOURING_PLAGUE_STRING, 40f, 200, ShadowPriestSettings.Instance.MultidotAvoidCC);
                        if (TargetForDevouringPlague != null && TargetForDevouringPlague.Distance - TargetForDevouringPlague.CombatReach - 1 <= 40f)
                        {
                            utils.LogActivity("AUTO CHOOSE BETTER TARGET DEVOURING_PLAGUE ", TargetForDevouringPlague.SafeName);
                            return utils.Cast(DEVOURING_PLAGUE, TargetForDevouringPlague);
                        }
                    }
                    
                }
                //mind_sear insanity
                if (Me.IsChanneling && Me.ChanneledCastingSpellId == SEARING_INSANITY)
                {
                    return true;
                } 

                //insanity
                if (utils.isAuraActive(SHADOW_WORD_INSANITY) || (Me.IsChanneling && Me.ChanneledCastingSpellId == MIND_FLY_INSANITY))
                {
                    if (Me.IsChanneling && Me.ChanneledCastingSpellId == MIND_FLY_INSANITY)
                    {
                        if (Me.CurrentChannelTimeLeft.TotalMilliseconds <= 350 + (2 * StyxWoW.WoWClient.Latency) && utils.isAuraActive(SHADOW_WORD_INSANITY))
                        {
                            utils.LogActivity("procworks: REFRESH MIND_FLY_INSANITY", target.SafeName);
                            return utils.Cast(MIND_FLY_INSANITY, target);
                        }
                        return true;
                    }
                    if (Me.IsFacing(target))
                    {
                        utils.LogActivity("procworks: MIND_FLY_INSANITY", target.SafeName);
                        return utils.Cast(MIND_FLY_INSANITY, target);
                    }
                }
                
                if (Me.IsFacing(target) && utils.PlayerCountBuff(SURGE_OF_DARKNESS) > 0)
                {
                    utils.LogActivity("procworks: MIND_SPIKE", target.SafeName);
                    return utils.Cast(MIND_SPIKE, target);
                }
                /*if (Me.GetCurrentPower(WoWPowerType.ShadowOrbs) < MaxOrbs)
                {
                    WoWUnit candidateSWD_target = utils.FirstShadowWordDeath_Target(40f, ShadowPriestSettings.Instance.AvoidCC, ExtraUtilsSettings.Instance.UseBossLogic);
                    if (candidateSWD_target != null)
                    {
                        utils.LogActivity("Found mob candidate for SW: Death:", candidateSWD_target.SafeName);
                        return utils.Cast(SHADOW_WORD_DEATH, candidateSWD_target);
                    }
                }*/
                        
            }
            return false;
        }

        private bool CC()
        {
            if (utils.CanCast(PSYCHIC_SCREAM) && ShadowPriestSettings.Instance.UsePsychicScream && Me.Combat && (utils.AllAttaccableEnemyMobsInRange(8).Count() >= 1))
            {
                utils.LogActivity("PSYCHIC_SCREAM");
                return utils.Cast(PSYCHIC_SCREAM);
            }
            if ( utils.CanCast(VOID_TENDRILS) && ShadowPriestSettings.Instance.UseVoidTendrils && Me.Combat && (utils.AllAttaccableEnemyMobsInRange(8).Count() >= 1))
            {
                utils.LogActivity("VOID_TENDRILS");
                return utils.Cast(VOID_TENDRILS);
            }
            if (utils.CanCast(PSYFIEND) && ShadowPriestSettings.Instance.UsePsyfiend && Me.Combat && (utils.AllAttaccableEnemyMobsInRange(20).Count() >= 1))
            {
                utils.LogActivity("PSYFIEND");
                utils.Cast(PSYFIEND);
                return SpellManager.ClickRemoteLocation(Me.Location);
            }

            return false;
        }

        private bool DispellMagic()
        {
            if (ShadowPriestSettings.Instance.UseDispellMagic && Me.CurrentTarget != null && Me.CurrentTarget.Attackable && Me.CurrentTarget.IsAlive
                && utils.CanCast(DISPELL_MAGIC,Me.CurrentTarget,true))
            {
                if (utils.EnemyNeedDispellASAP(Me.CurrentTarget))
                {
                    utils.LogActivity("DISPELL_MAGIC", Me.CurrentTarget.SafeName);
                    return utils.Cast(DISPELL_MAGIC, Me.CurrentTarget);
                }
            }
            return false;
        }

        private bool Multidot()
        {
            if (target != null && target.Distance - target.CombatReach - 1 <= 40f && !Me.IsCasting && !utils.IsGlobalCooldown())
            {
                //apply dot to my main target

                if (utils.MyAuraTimeLeft(SHADOW_WORD_PAIN, target) <= 5400
                    && !utils.isAuraActive(SHADOW_WORD_INSANITY) && !(Me.IsChanneling && Me.ChanneledCastingSpellId == MIND_FLY_INSANITY))
                {
                    utils.LogActivity("SHADOW_WORD_PAIN", target.SafeName);
                    return utils.Cast(SHADOW_WORD_PAIN, target);
                }
                if (!Me.IsMoving && utils.MyAuraTimeLeft(VAMPIRIC_TOUCH, target) <= 5500
                    && !utils.isAuraActive(SHADOW_WORD_INSANITY) && !(Me.IsChanneling && Me.ChanneledCastingSpellId == MIND_FLY_INSANITY))
                {
                    utils.LogActivity("VAMPIRIC_TOUCH", target.SafeName);
                    return utils.Cast(VAMPIRIC_TOUCH, target);
                }
            }
            if (ShadowPriestSettings.Instance.MultidotEnabled
                && Me.GetCurrentPower(WoWPowerType.ShadowOrbs) < MaxOrbs
                && !(utils.MyAuraTimeLeft(VAMPIRIC_TOUCH, target) < 5500)
                && !(utils.MyAuraTimeLeft(SHADOW_WORD_PAIN, target) < 5400)
                && !utils.isAuraActive(SHADOW_WORD_INSANITY)
                && !(Me.IsChanneling && Me.ChanneledCastingSpellId == MIND_FLY_INSANITY)
                && !(utils.PlayerCountBuff(SURGE_OF_DARKNESS) > 0)
                && !utils.isAuraActive(MIND_BLAST_PROC)
                && !Me.IsCasting && !utils.IsGlobalCooldown())
            {
                int enemyNumber = 0;
                if(ExtraUtilsSettings.Instance.provinGround_Targeting)
                    enemyNumber = utils.AllAttaccableEnemyMobsInRange(40f, ShadowPriestSettings.Instance.MultidotAvoidCC).Count();
                else
                    enemyNumber = utils.AllAttaccableEnemyMobsInRangeTargettingMyParty(40f, ShadowPriestSettings.Instance.MultidotAvoidCC).Count();
                if (enemyNumber >= ShadowPriestSettings.Instance.Multidot_SW_Pain_EnemyNumberMin || enemyNumber >= ShadowPriestSettings.Instance.Multidot_VampiricTouch_EnemyNumberMin)
                {
                    WoWUnit TargetForMultidot = null;
                    //apply  ShadowWord:Pain and always refresh it right before the last tick;
                    if (utils.CanCast(SHADOW_WORD_PAIN) && utils.AllEnemyMobsHasMyAura(SHADOW_WORD_PAIN).Count() < ShadowPriestSettings.Instance.Multidot_SW_Pain_EnemyNumberMax)
                    {
                        TargetForMultidot = utils.NextApplyAuraTarget(SHADOW_WORD_PAIN_STRING, 40f, 5400, ShadowPriestSettings.Instance.MultidotAvoidCC);
                        if (TargetForMultidot != null && TargetForMultidot.Distance - TargetForMultidot.CombatReach -1 <= 40f)
                        {
                            utils.LogActivity("   MULTIDOT SHADOW_WORD_PAIN  " , TargetForMultidot.SafeName);
                            return utils.Cast(SHADOW_WORD_PAIN, TargetForMultidot);
                        }
                    }
                    if (!Me.IsMoving && utils.AllEnemyMobsHasMyAura(VAMPIRIC_TOUCH).Count() < ShadowPriestSettings.Instance.Multidot_VampiricTouch_EnemyNumberMax)
                    {
                        TargetForMultidot = utils.NextApplyAuraTarget(VAMPIRIC_TOUCH_STRING, 40f, 5500, ShadowPriestSettings.Instance.MultidotAvoidCC);
                        if (TargetForMultidot != null && TargetForMultidot.Distance - TargetForMultidot.CombatReach - 1 <= 40f)
                        {
                            utils.LogActivity("VAMPIRIC_TOUCH", TargetForMultidot.SafeName);
                            return utils.Cast(VAMPIRIC_TOUCH, TargetForMultidot);
                        }
                    }
                }
                return false;
            }
            return false;
        }

        private bool AOE_Healing()
        {
            if (utils.CanCast(VAMPIRIC_EMBRANCE) && (utils.GetMemberCountBelowThreshold(ShadowPriestSettings.Instance.VampiricEmbranceHP) >= ShadowPriestSettings.Instance.VampiricEmbranceNumber))
            {           
                utils.LogActivity("VAMPIRIC_EMBRANCE");
                return utils.Cast(VAMPIRIC_EMBRANCE);

            }
            return false;
        }

        private bool PowerInfusion()
        {
            if(ShadowPriestSettings.Instance.PowerInfusionUse == ShadowPriestSettings.PowerInfusionUseType.COOLDOWN && utils.CanCast(POWER_INFUSION))
            {
                utils.LogActivity("POWER_INFUSION ");
                return utils.Cast(POWER_INFUSION);
            }
            else if (ShadowPriestSettings.Instance.PowerInfusionUse == ShadowPriestSettings.PowerInfusionUseType.BOSS && utils.CanCast(POWER_INFUSION)
                && extra.IsTargetBoss())
            {
                utils.LogActivity("POWER_INFUSION ");
                return utils.Cast(POWER_INFUSION);
            } 
            return false;
        }

        public bool CombatRotation()
        {
            SetTargetToAttack();
            extra.UseHealPotion_Healthstone();
            if (HotkeyHandle()) return true;
            if (extra.UseRacials()) return true;
            if (extra.UseTrinket1()) return true;
            if (extra.UseTrinket2()) return true;
            if (extra.UseManaItem()) return true;
            while (PowerInfusion()) return true;
            while (Interrupt()) return true;
            while (ProcWork()) return true;
            while (CC()) return true;
            while (AOE_Healing()) return true;
            while (Self()) return true;

            if ((SoloBotType || ShadowPriestSettings.Instance.movementEnabled) && Me.CurrentTarget != null && Me.IsMoving && Me.CurrentTarget.InLineOfSpellSight && Me.CurrentTarget.Distance - Me.CurrentTarget.CombatReach - 1 <= ShadowPriestSettings.Instance.PullDistance)
            {
                Navigator.PlayerMover.MoveStop();
            }

            if (target != null && target.Distance - target.CombatReach - 1 <= 40f)
            {
                if ((ShadowPriestSettings.Instance.AutofaceTarget || SoloBotType) && !Me.IsFacing(target) && !Me.IsMoving)
                {
                    Me.SetFacing(target);
                }

                //DW:death
                if (Me.GetCurrentPower(WoWPowerType.ShadowOrbs) < MaxOrbs && target.HealthPercent <= 20
                    && utils.GetSpellCooldown(SHADOW_WORD_DEATH).Milliseconds <= 2 * StyxWoW.WoWClient.Latency)
                {
                    utils.LogActivity("SHADOW_WORD_DEATH", target.SafeName);
                    return utils.Cast(SHADOW_WORD_DEATH, target);
                }

                if (!ShadowPriestSettings.Instance.AvoidAOE)
                {
                    //aoe
                    if (utils.AllAttaccableEnemyMobsInRangeFromTarget(Me, 40f, ExtraUtilsSettings.Instance.provinGround_Targeting).Count() >= ShadowPriestSettings.Instance.CascadeHaloDivineStarNumber
                        && ShadowPriestSettings.Instance.Use_Halo_Cascade_Divine)
                    {
                        if (utils.CanCast(HALO))
                        {
                            utils.LogActivity("HALO");
                            return utils.Cast(HALO);
                        }
                        else if (utils.CanCast(CASCADE, target))
                        {
                            utils.LogActivity("CASCADE", target.SafeName);
                            return utils.Cast(CASCADE, target);
                        }
                    }
                    //divine star
                    if (!Me.IsMoving && utils.CanCast(DIVINE_STAR)
                        && utils.FacingUnit(30, 180, false, true).Count() >= ShadowPriestSettings.Instance.CascadeHaloDivineStarNumber
                        && ShadowPriestSettings.Instance.Use_Halo_Cascade_Divine)
                    {
                        utils.LogActivity("DIVINE_STAR");
                        return utils.Cast(DIVINE_STAR);
                    }
                    //MindSear
                    if (!Me.IsMoving && Me.GetCurrentPower(WoWPowerType.ShadowOrbs) < MaxOrbs && ShadowPriestSettings.Instance.UseMindSear)
                    {
                        enemyAroundOffTank = 0;
                        enemyAroundMainTank = 0;
                        if (tank != null && tank.Guid != Me.Guid && tank.IsAlive && tank.Distance - tank.CombatReach - 1 <= 40f)
                            enemyAroundMainTank = utils.AllAttaccableEnemyMobsInRangeFromTarget(tank, 10, ExtraUtilsSettings.Instance.provinGround_Targeting).Count();
                        if (off_tank != null && off_tank.Guid != Me.Guid && off_tank.IsAlive && off_tank.Distance - off_tank.CombatReach - 1 <= 40f)
                            enemyAroundOffTank = utils.AllAttaccableEnemyMobsInRangeFromTarget(off_tank, 10, ExtraUtilsSettings.Instance.provinGround_Targeting).Count();
                        if (enemyAroundMainTank >= enemyAroundOffTank && enemyAroundMainTank >= ShadowPriestSettings.Instance.MindSearEnemyNumberMin)
                        {
                            //devouring plague
                            if (Me.GetCurrentPower(WoWPowerType.ShadowOrbs) >= 3)
                            {
                                if (!utils.isMyAuraActive(DEVOURING_PLAGUE_STRING, target))
                                {
                                    utils.LogActivity("procworks: DEVOURING_PLAGUE", target.SafeName);
                                    return utils.Cast(DEVOURING_PLAGUE, target);
                                }
                            }
                            if (Me.IsChanneling && Me.ChanneledCastingSpellId == MIND_SEAR)
                            {
                                return true;
                            }
                            utils.LogActivity("MIND SEAR ", tank.Class.ToString());
                            //SetNextChannelMSSpellAllowed();
                            return utils.Cast(MIND_SEAR, tank);
                        }
                        else if (enemyAroundOffTank >= enemyAroundMainTank && enemyAroundOffTank >= ShadowPriestSettings.Instance.MindSearEnemyNumberMin)
                        {
                            //devouring plague
                            if (Me.GetCurrentPower(WoWPowerType.ShadowOrbs) >= 3)
                            {
                                if (!utils.isMyAuraActive(DEVOURING_PLAGUE_STRING, target))
                                {
                                    utils.LogActivity("procworks: DEVOURING_PLAGUE", target.SafeName);
                                    return utils.Cast(DEVOURING_PLAGUE, target);
                                }
                            }
                            if (Me.IsChanneling && Me.ChanneledCastingSpellId == MIND_SEAR)
                            {
                                return true;
                            }
                            utils.LogActivity("MIND SEAR ", off_tank.Class.ToString());
                            return utils.Cast(MIND_SEAR, off_tank);
                        }
                        else if ((SoloBotType || ShadowPriestSettings.Instance.MindSearAlsoOnEnemies) && Me.CurrentTarget != null && Me.CurrentTarget.IsAlive && utils.AllAttaccableEnemyMobsInRangeFromTarget(Me.CurrentTarget, 10f, ExtraUtilsSettings.Instance.provinGround_Targeting).Count() >= ShadowPriestSettings.Instance.MindSearEnemyNumberMin)
                        {
                            //devouring plague
                            if (Me.GetCurrentPower(WoWPowerType.ShadowOrbs) >= 3)
                            {
                                if (!utils.isMyAuraActive(DEVOURING_PLAGUE_STRING, target))
                                {
                                    utils.LogActivity("procworks: DEVOURING_PLAGUE", target.SafeName);
                                    return utils.Cast(DEVOURING_PLAGUE, target);
                                }
                            }
                            if (Me.IsChanneling && Me.ChanneledCastingSpellId == MIND_SEAR)
                            {
                                return true;
                            }
                            utils.LogActivity("MIND SEAR ", Me.CurrentTarget.SafeName);
                            return utils.Cast(MIND_SEAR, Me.CurrentTarget);
                        }
                    }
                }
                while (Multidot()) return true;
                //mind blast
                if ((!Me.IsMoving || utils.isAuraActive(MIND_BLAST_PROC)) 
                    && Me.IsFacing(target)
                    && Me.GetCurrentPower(WoWPowerType.ShadowOrbs) < MaxOrbs
                    && utils.GetSpellCooldown(MIND_BLAST).TotalMilliseconds <= 2 * StyxWoW.WoWClient.Latency)
                    /*&& !utils.isAuraActive(SHADOW_WORD_INSANITY) && !(Me.IsChanneling && Me.ChanneledCastingSpellId == MIND_FLY_INSANITY))*/
                {
                    utils.LogActivity("MIND_BLAST", target.SafeName);
                    return utils.Cast(MIND_BLAST, target);
                }

                if (Me.CurrentTarget != null && Me.CurrentTarget.IsAlive && utils.TimeToDeath(Me.CurrentTarget) >= 12
                    && Me.CurrentTarget.Attackable && Me.CurrentTarget.InLineOfSpellSight
                    && Me.CurrentTarget.Distance - Me.CurrentTarget.CombatReach - 1 <= RangeOfAttack )
                {
                    if (utils.CanCast(SHADOWFIEND))
                    {
                        utils.LogActivity("SHADOWFIEND", Me.CurrentTarget.SafeName);
                        return utils.Cast(SHADOWFIEND, Me.CurrentTarget);
                    }
                    if (utils.CanCast(MINDBENDER))
                    {
                        utils.LogActivity("MINDBENDER", Me.CurrentTarget.SafeName);
                        return utils.Cast(MINDBENDER, Me.CurrentTarget);
                    }
                }

                
                if (Me.IsChanneling /*&& Me.ChanneledCastingSpellId == MIND_FLY*/)
                {
                    return true;
                }

                if (!utils.IsGlobalCooldown() && !Me.IsMoving && Me.GetCurrentPower(WoWPowerType.ShadowOrbs) < MaxOrbs
                    && !(utils.MyAuraTimeLeft(VAMPIRIC_TOUCH, target) < 5500)
                    && !(utils.MyAuraTimeLeft(SHADOW_WORD_PAIN, target) < 5400) 
                    && !utils.isAuraActive(SHADOW_WORD_INSANITY)
                    && !(Me.IsChanneling && Me.ChanneledCastingSpellId == MIND_FLY_INSANITY) 
                    && !(utils.PlayerCountBuff(SURGE_OF_DARKNESS) > 0)
                    && !utils.isAuraActive(MIND_BLAST_PROC))
                {
                    utils.LogActivity("MIND_FLY", target.SafeName);
                    return utils.Cast(MIND_FLY, target);
                

                }

                return false;
            }
            else if (ShadowPriestSettings.Instance.movementEnabled && Me.CurrentTarget != null && !Me.CurrentTarget.IsDead && (!Me.CurrentTarget.InLineOfSpellSight || Me.CurrentTarget.Distance - Me.CurrentTarget.CombatReach - 1 > ShadowPriestSettings.Instance.PullDistance))
            {
                movement.KingHealMove(Me.CurrentTarget, ShadowPriestSettings.Instance.PullDistance);
            }

            
            return false;

        }


        WoWUnit deathCandidate = null;

        private bool AutoDeathTargetAttack()
        {
            if (ShadowPriestSettings.Instance.TargetTypeSelected == ShadowPriestSettings.TargetType.AUTO)
            {
                if (ExtraUtilsSettings.Instance.provinGround_Targeting)
                    deathCandidate = utils.getAnyHPTargetToAttack(40f, 20);
                else
                    deathCandidate = utils.getHPTargetToAttack(40f, tank, 20, ShadowPriestSettings.Instance.AvoidCC);
            }
            if (deathCandidate != null && Me.GetCurrentPower(WoWPowerType.ShadowOrbs) < MaxOrbs
                    && utils.GetSpellCooldown(SHADOW_WORD_DEATH).Milliseconds <= 2 * StyxWoW.WoWClient.Latency)
            {
                if (!Me.IsFacing(deathCandidate) && !Me.IsMoving)
                    deathCandidate.Face();
                utils.LogActivity("AutoDeathTargetAttack: SHADOW_WORD_DEATH", deathCandidate.SafeName);
                return utils.Cast(SHADOW_WORD_DEATH, deathCandidate);
            }
            return false;
        }


        public bool DotWeavingRotation()
        {
            SetTargetToAttack();
            extra.UseHealPotion_Healthstone();
            if (extra.UseRacials()) return true;
            if (extra.UseTrinket1()) return true;
            if (extra.UseTrinket2()) return true;
            if (extra.UseManaItem()) return true;
            while (PowerInfusion()) return true;
            while (Interrupt()) return true;
            while (DotWeavingProcWork()) return true;
            while (CC()) return true;
            while (AOE_Healing()) return true;
            while (Self()) return true;
            


            if (target != null && target.Distance - target.CombatReach - 1 <= 40f)
            {
                if ((ShadowPriestSettings.Instance.AutofaceTarget || SoloBotType) && !Me.IsFacing(target) && !Me.IsMoving)
                {
                    Me.SetFacing(target);
                }

                //DW:death
                if (Me.GetCurrentPower(WoWPowerType.ShadowOrbs) < MaxOrbs && target.HealthPercent <= 20
                    && utils.GetSpellCooldown(SHADOW_WORD_DEATH).Milliseconds <= 2 * StyxWoW.WoWClient.Latency)
                {
                    utils.LogActivity("SHADOW_WORD_DEATH", target.SafeName);
                    return utils.Cast(SHADOW_WORD_DEATH, target);
                }

                if (!ShadowPriestSettings.Instance.AvoidAOE)
                {
                    //aoe
                    if (utils.AllAttaccableEnemyMobsInRangeFromTarget(Me, 40f, ExtraUtilsSettings.Instance.provinGround_Targeting).Count() >= ShadowPriestSettings.Instance.CascadeHaloDivineStarNumber
                        && ShadowPriestSettings.Instance.Use_Halo_Cascade_Divine)
                    {
                        if (utils.CanCast(HALO))
                        {
                            utils.LogActivity("HALO");
                            return utils.Cast(HALO);
                        }
                        else if (utils.CanCast(CASCADE))
                        {
                            utils.LogActivity("CASCADE", target.SafeName);
                            return utils.Cast(CASCADE, target);
                        }
                    }
                    //divine star
                    if (!Me.IsMoving && utils.CanCast(DIVINE_STAR)
                        && utils.FacingUnit(30, 180, false, true).Count() >= ShadowPriestSettings.Instance.CascadeHaloDivineStarNumber
                        && ShadowPriestSettings.Instance.Use_Halo_Cascade_Divine)
                    {
                        utils.LogActivity("DIVINE_STAR");
                        return utils.Cast(DIVINE_STAR);
                    }
                    //MindSear
                    if (!Me.IsMoving && Me.GetCurrentPower(WoWPowerType.ShadowOrbs) < MaxOrbs && ShadowPriestSettings.Instance.UseMindSear)
                    {
                        enemyAroundOffTank = 0;
                        enemyAroundMainTank = 0;
                        if (tank != null && tank.Guid != Me.Guid && tank.IsAlive && tank.Distance - tank.CombatReach - 1 <= 40f)
                            enemyAroundMainTank = utils.AllAttaccableEnemyMobsInRangeFromTarget(tank, 10f, ExtraUtilsSettings.Instance.provinGround_Targeting).Count();
                        if (off_tank != null && off_tank.Guid != Me.Guid && off_tank.IsAlive && off_tank.Distance - off_tank.CombatReach - 1 <= 40f)
                            enemyAroundOffTank = utils.AllAttaccableEnemyMobsInRangeFromTarget(off_tank, 10f, ExtraUtilsSettings.Instance.provinGround_Targeting).Count();
                        if (enemyAroundMainTank >= enemyAroundOffTank && enemyAroundMainTank >= ShadowPriestSettings.Instance.MindSearEnemyNumberMin)
                        {
                            //devouring plague
                            if (Me.GetCurrentPower(WoWPowerType.ShadowOrbs) >= 3 && !utils.isMyAuraActive(DEVOURING_PLAGUE_STRING, target))
                            {
                                utils.LogActivity("procworks: DEVOURING_PLAGUE", target.SafeName);
                                return utils.Cast(DEVOURING_PLAGUE, target);
                            }
                            if (Me.IsChanneling && Me.ChanneledCastingSpellId == MIND_SEAR)
                            {
                                return true;
                            }
                            utils.LogActivity("MIND SEAR ", tank.Class.ToString());
                            //SetNextChannelMSSpellAllowed();
                            return utils.Cast(MIND_SEAR, tank);
                        }
                        else if (enemyAroundOffTank >= enemyAroundMainTank && enemyAroundOffTank >= ShadowPriestSettings.Instance.MindSearEnemyNumberMin)
                        {
                            //devouring plague
                            if (Me.GetCurrentPower(WoWPowerType.ShadowOrbs) >= 3 && !utils.isMyAuraActive(DEVOURING_PLAGUE_STRING, target))
                            {
                                utils.LogActivity("procworks: DEVOURING_PLAGUE", target.SafeName);
                                return utils.Cast(DEVOURING_PLAGUE, target);
                            }
                            if (Me.IsChanneling && Me.ChanneledCastingSpellId == MIND_SEAR)
                            {
                                return true;
                            }
                            utils.LogActivity("MIND SEAR ", off_tank.Class.ToString());
                            return utils.Cast(MIND_SEAR, off_tank);
                        }
                        else if ((SoloBotType || ShadowPriestSettings.Instance.MindSearAlsoOnEnemies) && Me.CurrentTarget != null && Me.CurrentTarget.IsAlive && utils.AllAttaccableEnemyMobsInRangeFromTarget(Me.CurrentTarget, 10f, ExtraUtilsSettings.Instance.provinGround_Targeting).Count() >= ShadowPriestSettings.Instance.MindSearEnemyNumberMin)
                        {
                            //devouring plague
                            if (Me.GetCurrentPower(WoWPowerType.ShadowOrbs) >= 3 && !utils.isMyAuraActive(DEVOURING_PLAGUE_STRING, target))
                            {
                                utils.LogActivity("procworks: DEVOURING_PLAGUE", target.SafeName);
                                return utils.Cast(DEVOURING_PLAGUE, target);
                            }
                            if (Me.IsChanneling && Me.ChanneledCastingSpellId == MIND_SEAR)
                            {
                                return true;
                            }
                            utils.LogActivity("MIND SEAR ", Me.CurrentTarget.SafeName);
                            return utils.Cast(MIND_SEAR, Me.CurrentTarget);
                        }
                    }
                }

                while (DotWeavingMultidot()) return true;

                //mind blast
                if (Me.GetCurrentPower(WoWPowerType.ShadowOrbs) < MaxOrbs
                    && Me.IsFacing(target)
                    && utils.GetSpellCooldown(MIND_BLAST).TotalMilliseconds <= 2 * StyxWoW.WoWClient.Latency)
                    /*&& !utils.isAuraActive(SHADOW_WORD_INSANITY) && !(Me.IsChanneling && Me.ChanneledCastingSpellId == MIND_FLY_INSANITY))*/
                {
                    utils.LogActivity("MIND_BLAST", target.SafeName);
                    return utils.Cast(MIND_BLAST, target);
                }

                if (Me.CurrentTarget != null && Me.CurrentTarget.IsAlive && utils.TimeToDeath(Me.CurrentTarget) >= 12
                    && Me.CurrentTarget.Attackable && Me.CurrentTarget.InLineOfSpellSight
                    && Me.CurrentTarget.Distance - Me.CurrentTarget.CombatReach - 1 <= RangeOfAttack)
                {
                    if (utils.CanCast(SHADOWFIEND))
                    {
                        utils.LogActivity("SHADOWFIEND", Me.CurrentTarget.SafeName);
                        return utils.Cast(SHADOWFIEND, Me.CurrentTarget);
                    }
                    if (utils.CanCast(MINDBENDER))
                    {
                        utils.LogActivity("MINDBENDER", Me.CurrentTarget.SafeName);
                        return utils.Cast(MINDBENDER, Me.CurrentTarget);
                    }
                }

                if ((!Me.IsCasting || Me.IsChanneling) && (!Me.IsMoving || utils.PlayerCountBuff(SURGE_OF_DARKNESS) > 0) && Me.GetCurrentPower(WoWPowerType.ShadowOrbs) < MaxOrbs
                    && !(utils.GetSpellCooldown(MIND_BLAST).TotalMilliseconds <= 2 * StyxWoW.WoWClient.Latency))
                {
                    //if (!utils.isMyAuraActive(DEVOURING_PLAGUE_STRING, target) && !utils.isMyAuraActive(SHADOW_WORD_PAIN,target) && !utils.isMyAuraActive(VAMPIRIC_TOUCH,target))
                    double mind_spike_cast_time = utils.GetSpellCastTime("Mind Spike").TotalMilliseconds;
                    if ( utils.PlayerCountBuff(SURGE_OF_DARKNESS) > 0 || (utils.MyAuraTimeLeft(DEVOURING_PLAGUE_STRING, target) <= mind_spike_cast_time && utils.MyAuraTimeLeft(SHADOW_WORD_PAIN, target) <= mind_spike_cast_time && utils.MyAuraTimeLeft(VAMPIRIC_TOUCH, target) <= mind_spike_cast_time))
                    {
                        utils.LogActivity("MIND_SPIKE", target.SafeName);
                        return utils.Cast(MIND_SPIKE, target);
                    }
                    else if (!Me.IsChanneling && !utils.isAuraActive(SHADOW_WORD_INSANITY) && (utils.isMyAuraActive(DEVOURING_PLAGUE_STRING, target) || utils.isMyAuraActive(SHADOW_WORD_PAIN, target) || utils.isMyAuraActive(VAMPIRIC_TOUCH, target)))
                    {
                        utils.LogActivity("MIND_FLY", target.SafeName);
                        return utils.Cast(MIND_FLY, target);
                    }
                }

                return false;
            }
            else if (ShadowPriestSettings.Instance.movementEnabled && Me.CurrentTarget != null && !Me.CurrentTarget.IsDead && (!Me.CurrentTarget.InLineOfSpellSight || Me.CurrentTarget.Distance - Me.CurrentTarget.CombatReach - 1 > ShadowPriestSettings.Instance.PullDistance))
            {
                movement.KingHealMove(Me.CurrentTarget, ShadowPriestSettings.Instance.PullDistance);
            }


            return false;
        }

        private bool DotWeavingProcWork()
        {
            if (target != null && target.Distance - target.CombatReach - 1 <= 40f)
            {
                if ((ShadowPriestSettings.Instance.AutofaceTarget || SoloBotType) && !Me.IsFacing(target) && !Me.IsMoving)
                {
                    Me.SetFacing(target);
                }
                if (Me.GetCurrentPower(WoWPowerType.ShadowOrbs) < MaxOrbs && target.HealthPercent <= 20
                    && utils.GetSpellCooldown(SHADOW_WORD_DEATH).Milliseconds <= 2 * StyxWoW.WoWClient.Latency)
                {
                    utils.LogActivity("procworks: SHADOW_WORD_DEATH", target.SafeName);
                    return utils.Cast(SHADOW_WORD_DEATH, target);
                }
                if (AutoDeathTargetAttack()) return true;
                if (Me.GetCurrentPower(WoWPowerType.ShadowOrbs) < MaxOrbs
                    && Me.IsFacing(target)
                    && utils.GetSpellCooldown(MIND_BLAST).TotalMilliseconds <= 2 * StyxWoW.WoWClient.Latency)
                {
                    utils.LogActivity("procworks: MIND_BLAST", target.SafeName);
                    return utils.Cast(MIND_BLAST, target);
                }
                //devouring plague
                if (Me.GetCurrentPower(WoWPowerType.ShadowOrbs) >= 3
                    && ((talents.IsSelected(9) && utils.isMyAuraActive(SHADOW_WORD_PAIN, target) && utils.isMyAuraActive(VAMPIRIC_TOUCH, target)) || !talents.IsSelected(9)))
                {
                    if (!utils.isMyAuraActive(DEVOURING_PLAGUE_STRING, target))
                    {
                        utils.LogActivity("procworks: DEVOURING_PLAGUE", target.SafeName);
                        return utils.Cast(DEVOURING_PLAGUE, target);
                    }
                }
                
                //MindSear Insanity
                if (!Me.IsMoving && talents.IsSelected(9) && !Me.IsMoving && (Me.GetCurrentPower(WoWPowerType.ShadowOrbs) >= 3 || utils.isAuraActive(SHADOW_WORD_INSANITY)) && ShadowPriestSettings.Instance.UseMindSear)
                {
                    enemyAroundOffTank = 0;
                    enemyAroundMainTank = 0;
                    if (tank != null && tank.Guid != Me.Guid && tank.IsAlive && tank.Distance - tank.CombatReach - 1 <= 40f)
                        enemyAroundMainTank = utils.AllAttaccableEnemyMobsInRangeFromTarget(tank, 10f, ExtraUtilsSettings.Instance.provinGround_Targeting).Count();
                    if (off_tank != null && off_tank.Guid != Me.Guid && off_tank.IsAlive && off_tank.Distance - off_tank.CombatReach - 1 <= 40f)
                        enemyAroundOffTank = utils.AllAttaccableEnemyMobsInRangeFromTarget(off_tank, 10f, ExtraUtilsSettings.Instance.provinGround_Targeting).Count();
                    if (enemyAroundMainTank >= enemyAroundOffTank && enemyAroundMainTank >= ShadowPriestSettings.Instance.MindSearEnemyNumberMin)
                    {
                        //devouring plague
                        if (Me.GetCurrentPower(WoWPowerType.ShadowOrbs) >= 3 && !utils.isMyAuraActive(DEVOURING_PLAGUE_STRING, target))
                        {
                            utils.LogActivity("procworks: DEVOURING_PLAGUE", target.SafeName);
                            return utils.Cast(DEVOURING_PLAGUE, target);
                        }
                        if (Me.IsChanneling && Me.ChanneledCastingSpellId == SEARING_INSANITY)
                        {
                            if (Me.CurrentChannelTimeLeft.TotalMilliseconds <= 350 + (2 * StyxWoW.WoWClient.Latency) && utils.isAuraActive(SHADOW_WORD_INSANITY))
                            {
                                utils.LogActivity("procworks: REFRESH SEARING_INSANITY", tank.SafeName);
                                return utils.Cast(SEARING_INSANITY, tank);
                            }
                            return true;
                        }
                        utils.LogActivity("SEARING_INSANITY", tank.Class.ToString());
                        return utils.Cast(SEARING_INSANITY, tank);
                    }
                    else if (enemyAroundOffTank >= enemyAroundMainTank && enemyAroundOffTank >= ShadowPriestSettings.Instance.MindSearEnemyNumberMin)
                    {
                        //devouring plague
                        if (Me.GetCurrentPower(WoWPowerType.ShadowOrbs) >= 3 && !utils.isMyAuraActive(DEVOURING_PLAGUE_STRING, target))
                        {
                            utils.LogActivity("procworks: DEVOURING_PLAGUE", target.SafeName);
                            return utils.Cast(DEVOURING_PLAGUE, target);
                        }
                        if (Me.IsChanneling && Me.ChanneledCastingSpellId == SEARING_INSANITY)
                        {
                            if (Me.CurrentChannelTimeLeft.TotalMilliseconds <= 350 + (2 * StyxWoW.WoWClient.Latency) && utils.isAuraActive(SHADOW_WORD_INSANITY))
                            {
                                utils.LogActivity("procworks: REFRESH SEARING_INSANITY", off_tank.SafeName);
                                return utils.Cast(SEARING_INSANITY, off_tank);
                            }
                            return true;
                        }
                        utils.LogActivity("SEARING_INSANITY", off_tank.Class.ToString());
                        return utils.Cast(SEARING_INSANITY, off_tank);
                    }
                    else if ((SoloBotType || ShadowPriestSettings.Instance.MindSearAlsoOnEnemies) && Me.CurrentTarget != null && Me.CurrentTarget.IsAlive && utils.AllAttaccableEnemyMobsInRangeFromTarget(Me.CurrentTarget, 10f, ExtraUtilsSettings.Instance.provinGround_Targeting).Count() >= ShadowPriestSettings.Instance.MindSearEnemyNumberMin)
                    {
                        //devouring plague
                        if (Me.GetCurrentPower(WoWPowerType.ShadowOrbs) >= 3 && !utils.isMyAuraActive(DEVOURING_PLAGUE_STRING, target))
                        {
                            utils.LogActivity("procworks: DEVOURING_PLAGUE", target.SafeName);
                            return utils.Cast(DEVOURING_PLAGUE, target);
                        }
                        if (Me.IsChanneling && Me.ChanneledCastingSpellId == SEARING_INSANITY)
                        {
                            if (Me.CurrentChannelTimeLeft.TotalMilliseconds <= 350 + (2 * StyxWoW.WoWClient.Latency) && utils.isAuraActive(SHADOW_WORD_INSANITY))
                            {
                                utils.LogActivity("procworks: REFRESH SEARING_INSANITY", Me.CurrentTarget.SafeName);
                                return utils.Cast(SEARING_INSANITY, Me.CurrentTarget);
                            }
                            return true;
                        }
                        utils.LogActivity("SEARING_INSANITY", Me.CurrentTarget.SafeName);
                        return utils.Cast(SEARING_INSANITY, Me.CurrentTarget);
                    }
                }
                //insanity
                if (!Me.IsMoving && (utils.isAuraActive(SHADOW_WORD_INSANITY) || (Me.IsChanneling && Me.ChanneledCastingSpellId == MIND_FLY_INSANITY)))
                {
                    if (Me.IsChanneling && Me.ChanneledCastingSpellId == MIND_FLY_INSANITY)
                    {
                        if (Me.CurrentChannelTimeLeft.TotalMilliseconds <= 350 + (2 * StyxWoW.WoWClient.Latency) && utils.isAuraActive(SHADOW_WORD_INSANITY))
                        {
                            utils.LogActivity("procworks: REFRESH MIND_FLY_INSANITY", target.SafeName);
                            return utils.Cast(MIND_FLY_INSANITY, target);
                        }
                        return true;
                    }
                    if (Me.IsFacing(target))
                    {
                        utils.LogActivity("procworks: MIND_FLY_INSANITY", target.SafeName);
                        return utils.Cast(MIND_FLY_INSANITY, target);
                    }
                }           
                
                if (Me.IsFacing(target) && utils.PlayerCountBuff(SURGE_OF_DARKNESS) > 0)
                {
                    utils.LogActivity("procworks: MIND_SPIKE", target.SafeName);
                    return utils.Cast(MIND_SPIKE, target);
                }

              
            }
            return false;
        }

        private bool DotWeavingMultidot()
        {
            if (target != null && target.Distance - target.CombatReach - 1 <= 40f 
                && !Me.IsCasting && !utils.IsGlobalCooldown() && talents.IsSelected(9))
            {
                //apply dot to my main target
                if (!utils.isMyAuraActive(SHADOW_WORD_PAIN, target) && Me.GetCurrentPower(WoWPowerType.ShadowOrbs) == 5 && utils.TimeToDeath(target) > 10)
                {
                    utils.LogActivity("SHADOW_WORD_PAIN", target.SafeName);
                    return utils.Cast(SHADOW_WORD_PAIN, target);
                }
                if (!utils.isMyAuraActive(VAMPIRIC_TOUCH, target) && Me.GetCurrentPower(WoWPowerType.ShadowOrbs) == 5 && utils.TimeToDeath(target) > 10)
                {
                    utils.LogActivity("VAMPIRIC_TOUCH", target.SafeName);
                    return utils.Cast(VAMPIRIC_TOUCH, target);
                }
            }
            if (ShadowPriestSettings.Instance.MultidotEnabled
                && !Me.IsCasting && !utils.IsGlobalCooldown()
                && Me.GetCurrentPower(WoWPowerType.ShadowOrbs) < MaxOrbs
                && !utils.isAuraActive(SHADOW_WORD_INSANITY)
                && !(Me.IsChanneling && Me.ChanneledCastingSpellId == MIND_FLY_INSANITY)
                && !(utils.PlayerCountBuff(SURGE_OF_DARKNESS) > 0)
                && !(utils.GetSpellCooldown(MIND_BLAST).TotalMilliseconds <= 2 * StyxWoW.WoWClient.Latency))
            {
                int enemyNumber = 0;
                if (ExtraUtilsSettings.Instance.provinGround_Targeting)
                    enemyNumber = utils.AllAttaccableEnemyMobsInRange(40f, ShadowPriestSettings.Instance.MultidotAvoidCC).Count();
                else
                    enemyNumber = utils.AllAttaccableEnemyMobsInRangeTargettingMyParty(40f, ShadowPriestSettings.Instance.MultidotAvoidCC).Count();
                if (enemyNumber >= ShadowPriestSettings.Instance.Multidot_SW_Pain_EnemyNumberMin || enemyNumber >= ShadowPriestSettings.Instance.Multidot_VampiricTouch_EnemyNumberMin)
                {
                    WoWUnit TargetForMultidot = null;
                    //apply  ShadowWord:Pain and always refresh it right before the last tick;
                    if (utils.CanCast(SHADOW_WORD_PAIN) && utils.AllEnemyMobsHasMyAura(SHADOW_WORD_PAIN).Count() < ShadowPriestSettings.Instance.Multidot_SW_Pain_EnemyNumberMax)
                    {
                        TargetForMultidot = utils.NextApplyAuraTarget(SHADOW_WORD_PAIN_STRING, 40f, 5400, ShadowPriestSettings.Instance.MultidotAvoidCC,false,target);
                        if (TargetForMultidot != null && TargetForMultidot.Distance - TargetForMultidot.CombatReach - 1 <= 40f)
                        {
                            utils.LogActivity("DotWeaving   MULTIDOT SHADOW_WORD_PAIN  ", TargetForMultidot.SafeName);
                            return utils.Cast(SHADOW_WORD_PAIN, TargetForMultidot);
                        }
                    }
                    if (!Me.IsMoving && utils.AllEnemyMobsHasMyAura(VAMPIRIC_TOUCH).Count() < ShadowPriestSettings.Instance.Multidot_VampiricTouch_EnemyNumberMax)
                    {
                        TargetForMultidot = utils.NextApplyAuraTarget(VAMPIRIC_TOUCH_STRING, 40f, 5500, ShadowPriestSettings.Instance.MultidotAvoidCC,false,target);
                        if (TargetForMultidot != null && TargetForMultidot.Distance - TargetForMultidot.CombatReach - 1 <= 40f)
                        {
                            utils.LogActivity("DotWeaving   MULTIDOT VAMPIRIC_TOUCH  ", TargetForMultidot.SafeName);
                            return utils.Cast(VAMPIRIC_TOUCH, TargetForMultidot);

                        }
                    }
                }
                return false;
            }
            return false;
        }

        public override bool Combat
        {
            get
            {
                if ((Me.Mounted && !ShadowPriestSettings.Instance.AutoDismountOnCombat)
                    || !StyxWoW.IsInGame || !StyxWoW.IsInWorld || Me.Silenced
                    || (!ExtraUtilsSettings.Instance.FastRotation && (utils.IsGlobalCooldown() || (Me.IsCasting && ! utils.MeIsChanneling) ))
                    || utils.IsEatingOrDrinking() || IsCRPaused)
                    return false;

                tank = utils.SimpleGetTank(40f);
                if (tank == null || !tank.IsValid || !tank.IsAlive) tank = Me;

                if (tank != null && (lastTank == null || lastTank.Guid != tank.Guid))
                {
                    lastTank = tank;
                    utils.LogActivity(TANK_CHANGE, tank.Class.ToString());
                } off_tank = utils.SimpleGetOffTank(40f, tank);
                if (off_tank != null && (lastOffTank == null || lastOffTank.Guid != off_tank.Guid))
                {
                    lastOffTank = off_tank;
                    utils.LogActivity(OFF_TANK_CHANGE, off_tank.Class.ToString());
                }
                //update doublecast
                //utils.PulseDoubleCastEntries();
                if (CombatBuff()) return true;
                if (talents.IsSelected(19) && ShadowPriestSettings.Instance.EnableDotWeavingRotation)
                    return DotWeavingRotation();
                return CombatRotation();
            }
        }


    }
}
